﻿using System;
using System.ComponentModel;
using System.Threading;
using CI.Misc;
using CI.Organism;

namespace CI.PW.Models
{
    public class OrganismStatusModel : DataModel, IDisposable
    {
        public IOrganism organism { get; private set; }
        private static readonly TimeSpan RefreshRate = new TimeSpan(0, 0, 0, 0, 500);
        private readonly Timer _updateTimer;

        public OrganismStatusModel(IOrganism organism)
        {
            this.organism = organism;
            organism.EnergyChangeEvent += OnEnergyChange;
            organism.HeartbeatChangeEvent += OnHeartbeatChange;
            organism.RegistrationChangeEvent += OnRegistrationChange;
            organism.BornChangeEvent += OnBornChange;

            _updateTimer = new Timer(ScenarioUpdateDisplay, null, RefreshRate, RefreshRate);
        }

        private void ScenarioUpdateDisplay(object state)
        {
            if (_heartbeatUpdate)
            {
                _heartbeatUpdate = false;
                RaisePropertyChanged(HeartbeatPropertyChanged);
            }

            if (_energyUpdate)
            {
                _energyUpdate = false;
                RaisePropertyChanged(EnergyPropertyChanged);
            }

            if (_bornUpdate)
            {
                _bornUpdate = false;
                RaisePropertyChanged(BornPropertyChanged);
            }

            if (_registrationUpdate)
            {
                _registrationUpdate = true;
                RaisePropertyChanged(RegisteredPropertyChanged);
            }


        }

        private void OnBornChange()
        {
            _bornUpdate = true;
        }

        private void OnRegistrationChange()
        {
            _registrationUpdate = true;
        }

        private void OnEnergyChange(long inputValue)
        {
            _energyUpdate = true;
        }

        private void OnHeartbeatChange()
        {
            _heartbeatUpdate = true;
        }

        private bool _heartbeatUpdate;
        private bool _energyUpdate;
        private bool _bornUpdate;
        private bool _registrationUpdate;

        private static readonly PropertyChangedEventArgs HeartbeatPropertyChanged = new PropertyChangedEventArgs("Heartbeat");
        private static readonly PropertyChangedEventArgs EnergyPropertyChanged = new PropertyChangedEventArgs("Energy");
        private static readonly PropertyChangedEventArgs RegisteredPropertyChanged = new PropertyChangedEventArgs("Registered");
        private static readonly PropertyChangedEventArgs BornPropertyChanged = new PropertyChangedEventArgs("Born");


        public string Type { get { return organism.Zygote().ToString(); } }
        public long Heartbeat { get { return organism.HeartbeatCount; } }
        public long Energy { get { return organism.Energy; } }
        public bool Registered { get { return SimEnv.Instance.HostEnvPhysical.Registered(organism); } }
        public bool Born { get { return organism.Born; } }
        private bool isSelected = false;
        public bool IsSelected
        {
            get { return isSelected; }
            set
            {
                if (isSelected != value)
                {
                    isSelected = value;
                    RaisePropertyChanged("IsSelected");
                }
            }
        }

        public override string ToString()
        {
            return organism.ToString();
        }

        public void Dispose()
        {
            _updateTimer.Dispose();
            organism.EnergyChangeEvent -= OnEnergyChange;
            organism.HeartbeatChangeEvent -= OnHeartbeatChange;
            organism.RegistrationChangeEvent -= OnRegistrationChange;
            organism.BornChangeEvent -= OnBornChange;
        }
    }
}
